# -*- coding: utf-8 -*-
# @Time : 2022/6/20 11:32
# @Author : cheney
# @File : packet.py
# @Software: PyCharm
# @Site: www.cheney.cc
"""
    报文数据结构
    包含报文对象和二进制互转的方法

    数据字段content有两种情况：
        1）为基站下发的指令时，是instruction类型
        2）为反馈的数据时，是data类型
"""
from pi.model.instruction import instruction
import json
import datetime


class packet:
    _src_id = "127.0.0.1"
    _des_id = "127.0.0.1"
    pac_type = 0
    ctl_type = 0

    _timestamp = "2022-05-13 18:22:35"

    '''数据字段content具体是data还是instruction取决于_pac_type和_ctl_type'''
    content = None
    # _data = data()
    # _instruction = instruction

    '''一些常量'''
    PI_TO_PC = 1  # 基站->树莓派
    PC_TO_PI = 2  # 树莓派->基站
    PI_TO_PI = 3  # 树莓派->树莓派

    CAR_MOVE = 0  # 控制小车运动
    CAR_STOP = 1  # 停止小车运动
    BACK_HOME = 2  # 返回出发点
    SENSOR_UP = 3  # 开启传感器
    SENSOR_DOWN = 4  # 关闭传感器
    ROUTER = 5  # 转发报文
    INIT_CONF = 6  # 初始化 / 修改配置信息

    def __init__(self, src_id: str = "127.0.0.1", des_id: str = "127.0.0.1",
                 pac_type: int = 0, ctl_type: int = 0, content=None):
        self._src_id = src_id
        self._des_id = des_id
        self.pac_type = pac_type
        self.ctl_type = ctl_type
        self._timestamp = str(datetime.datetime.now())

        self.content = content

    def get_instruction(self) -> instruction:
        if self.pac_type == self.PC_TO_PI:
            return self.content
        else:
            raise ValueError(self.pac_type)
        # else:
        #     print("instruction error called")
        #     return None

    def get_data(self) -> content:
        if self.pac_type == self.PI_TO_PC:
            return self.content
        else:
            raise ValueError(self.pac_type)
        # else:
        #     return None

    def set_src_id(self, src_id: str):
        self._src_id = src_id

    def set_des_id(self, des_id: str):
        self._des_id = des_id

    def set_pac_type(self, pac_type: int):
        self.pac_type = pac_type

    def set_ctl_type(self, ctl_type: int):
        self.ctl_type = ctl_type

    def set_timestamp(self, timestamp: str):
        self._timestamp = timestamp

    def set_content(self, content):
        self._data = content

    # def set_content(self, content: instruction):  # python不支持重载
    #     self._data = content

    def to_bin(self, encoding: str = 'utf-8') -> bytes:
        return self.__to_json().encode(encoding=encoding)

    def from_bin(self, data_bin: bytes, encoding: str = 'utf-8') -> bool:
        """
        从一个二进制数据（socket获取到到报文）解析出数据，赋值给数据成员
        :param data_bin:
        :param encoding:
        :return:
        """
        try:
            data_json = json.loads(data_bin.decode(encoding))
        except json.JSONDecodeError:
            print("json.JSONDecodeError!!!")
            return False

        print(data_json)
        self._src_id = data_json["src_id"]
        self._des_id = data_json["dst_id"]
        self.pac_type = data_json["pac_type"]
        self.ctl_type = data_json["ctl_type"]
        self._timestamp = data_json["timestamp"]
        if self.ctl_type == self.PI_TO_PC:
            # todo:实际不需要这个判断，是这个选项即出错
            # my_data = data()
            # self.content = my_data.from_json(data_json["content"])
            pass
        else:
            self.content = instruction(ins_type=self.ctl_type)
            self.content.from_json(data_json["content"])

        return True

    def __to_json(self) -> json:
        ans = {
            "src_id": self._timestamp,
            "des_id": self._des_id,
            "pac_type": self.pac_type,
            "ctl_type": self.ctl_type,
            "timestamp": self._timestamp,
            "content": self.content.to_json()
        }

        return json.dumps(ans)

    # def __from_json(self):
    #     pass
